package com.social.service.impl;


import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.social.dao.PetitionDao;
import com.social.pojo.Petition;
import com.social.pojo.Result;
import com.social.pojo.dto.SmsDTO;
import com.social.pojo.dto.UserDTO;
import com.social.pojo.vto.PetitonVO;
import com.social.service.PetitionService;
import com.social.utils.RandomUtils;
import com.social.utils.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.social.constant.RabbitMqConstants.EXCHANGE_TOPIC_SMS;
import static com.social.constant.RabbitMqConstants.ROUTING_SMS_ITEM;
import static com.social.constant.RedisConstants.*;

/**
 * @author zero
 * @description 针对表【petition(信访)】的数据库操作Service实现
 * {@code @createDate} 2022-09-30 11:31:53
 */
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class PetitionServiceImpl extends ServiceImpl<PetitionDao, Petition>
        implements PetitionService {
    @Resource
    private PetitionDao petitionDao;
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private AmqpTemplate amqpTemplate;


    @Override
    public Result add(Petition petition) {
        UserDTO user = UserHolder.getUser();
       log.info("当前用户是"+user);
        String phone = user.getPhone();
        //redis中获取短信验证码
        String key = PETITION_CODE_KEY + phone;
        String cacheCode = stringRedisTemplate.opsForValue().get(key);
        //断验证码是否正确
        assert cacheCode != null;
        if (!cacheCode.equals(petition.getCode())) {
            return Result.fail(201, "验证码错误");
        }
        //设置字段的值
        String[] selectedOptions = petition.getSelectedOptions();
        String replace = String.join(",", selectedOptions);
        petition.setPeAddress(replace);
        LocalDateTime dateTime = LocalDateTime.now();
        petition.setCreatTime(dateTime);
        petition.setUserId(Long.valueOf(user.getId()));
        //保存到数据库
        boolean save = save(petition);
        if (save) {
            //发送保存查询码
            sendAndSaveFindCode(petition);
            return Result.ok(200,"信访成功，稍后我们会给您发送查询码");
        }
        return Result.fail(201, "信访失败");
    }

    public Result update(Petition petition) {
        LocalDateTime dateTime = LocalDateTime.now();
        petition.setCreatTime(dateTime);
        String[] selectedOptions = petition.getSelectedOptions();
        String replace = String.join(",", selectedOptions);
        petition.setPeAddress(replace);
        boolean update = updateById(petition);
        if (!update) {
            return Result.fail(201, "更新失败");
        }
        String key = PETITION_ID_KEY + petition.getPeId();
        stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(petition), PETITION_ID_TTL, TimeUnit.MINUTES);
        return Result.ok(200);
    }

    @Override
    public Result getPetitionById(Integer id) {
        String key = PETITION_ID_KEY + id;
        //获取redis的获取key
        String json = stringRedisTemplate.opsForValue().get(key);
        //直接从缓存中读
        if (json != null) {
            return Result.ok(200, JSONUtil.toBean(json, Petition.class));
        }
        Petition petition = getById(id);
        if (petition == null) {
            return Result.fail(200, "查询失败");
        }
        //存入缓存
        stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(petition), PETITION_ID_TTL, TimeUnit.MINUTES);
        return Result.ok(200, petition);
    }

    @Override
    public Result findByUserId(Integer currentPage, Integer pageSize) {
        //查询条件
        QueryWrapper<Petition> wrapper = Wrappers.query();
        UserDTO user = UserHolder.getUser();
        wrapper.eq("username", user.getUsername());
        Page<Petition> page = petitionDao.selectPage(new Page<>(currentPage, pageSize), wrapper);
        List<Petition> records = page.getRecords();
        if (records == null) {
            return Result.fail(200, "您没有信访记录");
        }
        return Result.ok(200, records);
    }

    @Override
    public Result findAll(Integer currentPage, Integer pageSize) {
        Page<Petition> petitionPage = petitionDao.selectPage(new Page<>(currentPage, pageSize), null);
        List<Petition> petitions = petitionPage.getRecords();
        if (petitions == null) {
            return Result.fail(201, "没有信访");
        }
        return Result.ok(200, petitions);
    }

    @Override
    public Result sendMessage() {
        //获取用户
        UserDTO user = UserHolder.getUser();
        if (user == null) {
            return Result.fail(201, "用户未登录");
        }
        String phone = user.getPhone();
        if (phone == null) {
            return Result.fail(201,"请完善手机号");
        }
        // TODO 发送验证码
        //1.从redis中获取验证码，如果缓存中有的话直接返回，没有的话从阿里云发送获取
        String key = PETITION_CODE_KEY + phone;
        String code = stringRedisTemplate.opsForValue().get(key);
        if(StringUtils.isNotEmpty(code)){
          return Result.ok(200,"验证码已发送") ;
        }
        code = RandomUtils.getFourBitRandom();
        SmsDTO smsDTO = new SmsDTO();
        smsDTO.setMessage(code);
        smsDTO.setMobile(phone);
        amqpTemplate.convertAndSend(EXCHANGE_TOPIC_SMS, ROUTING_SMS_ITEM, smsDTO);
        stringRedisTemplate.opsForValue().set(key,code,PETITION_CODE_TTL,TimeUnit.MINUTES);
        return Result.ok(200,"验证码发送中");
    }

    @Override
    public List<Petition> getTodayPetition() {
        LocalDate localDate = LocalDate.now();
        LocalDate yesterday = localDate.plusDays(-1);
        LocalDateTime start = yesterday.atTime(18, 0);
        LocalDateTime end = localDate.atTime(18, 0);
        QueryWrapper<Petition> wrapper = new QueryWrapper<>();
        wrapper.ge("creat_time", start);
        wrapper.le("creat_time", end);
        List<Petition> petitionList = petitionDao.selectList(wrapper);
        return petitionList;
    }

    @Override
    public Result findByCondition(PetitonVO petitonVO) {
        QueryWrapper<Petition> wrapper = new QueryWrapper<>();
        if (petitonVO.getBeginTime() != null) {
            wrapper.ge("creat_time", petitonVO.getBeginTime());
        }
        if (petitonVO.getEndTime() != null) {
            wrapper.le("creat_time", petitonVO.getEndTime());
        }
        if (petitonVO.getStatus() != null) {
            wrapper.eq("pe_status", petitonVO.getStatus());
        }
        Page<Petition> petitionPage = petitionDao.selectPage(new Page<>(petitonVO.getCurrentPage(), petitonVO.getPageSize()), wrapper);
        List<Petition> petitions = petitionPage.getRecords();
        if (petitions == null) {
            return Result.fail(201, "，没有符合条件的数据");
        }
        return Result.ok(200, petitions);
    }

    @Override
    public Result deal(Petition reply) {
        Long peId = reply.getPeId();
        Petition petition = getById(peId);
        if (petition == null) {
            return Result.fail(201, "不存在信访");
        }
        boolean save = updateById(reply);
        if(save){
            return Result.ok(200,"信访回复成功");
        }
        return Result.fail(201, "信访回复失败");
    }

    public boolean sendAndSaveFindCode(Petition petition) {
        UserDTO user = UserHolder.getUser();
        System.out.println("获取的用户是" + user);
        String phone = user.getPhone();
        //从redis中取出查询码
        String key = PETITION_FINDCODE_KEY + petition.getPeId();
        String findCode = stringRedisTemplate.opsForValue().get(key);
        if(StringUtils.isNotEmpty(findCode)){
          return true;
        }
        //redis中没有码,发送码并保存
        findCode = RandomUtils.getSixBitRandom();
        SmsDTO smsDTO = new SmsDTO();
        smsDTO.setMessage(findCode);
        smsDTO.setMobile(phone);
        amqpTemplate.convertAndSend(EXCHANGE_TOPIC_SMS, ROUTING_SMS_ITEM, smsDTO);
        stringRedisTemplate.opsForValue().set(key,findCode);
        petition.setFindCode(findCode);
        boolean update = updateById(petition);
        log.info("查询码是否放入数据库"+update);
        return true;
    }

    @Override
    public Result findSpeedProcess(String findCode) {
        QueryWrapper<Petition> wrapper = new QueryWrapper<>();
        wrapper.eq("findcode", findCode);
        Petition petition = petitionDao.selectOne(wrapper);
        if (petition != null) {
            return Result.ok(200, petition);
        }
        return Result.fail(201, "无");
    }
}


